package cp2013;

import java.awt.event.*;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import javax.swing.*;

/**
 *
 * @author AcerXPS
 */
public class MainUI {

    private JFrame frame = new JFrame("Online Auction");
    private UserSystem system = new UserSystem();
    private static final int HEIGHT = 700;
    private static final int WIDTH = 700;
    private LoginUI loginUI;
    private HomeUI homeUI;
    private RegisterUI registerUI;
    private PlaceItemUI itemUI;
    private RechargeTokenUI rechargeUI;
    private LoginButtonListener loginUIListener = new LoginButtonListener();
    private HomePanelListener homePanelListener = new HomePanelListener();
    private PlaceItemListener placeItemUIListener = new PlaceItemListener();
    private RechargeListener rechargeUIListener = new RechargeListener();
    private BidButtonListener btnBidListener = new BidButtonListener();
    private RegisterButtonListener registerUIListener = new RegisterButtonListener();

    public void go() {
        //initiate panels
        loginUI = new LoginUI();
        loginUI.initiateLoginUI();


        //add listeners
        loginUI.addloginUIListener(loginUIListener);

        //show login UI
        frame.getContentPane().add(loginUI);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new java.awt.event.WindowAdapter() {

            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });
        frame.validate();
        frame.setSize(WIDTH, HEIGHT);
        if (!system.isConnectionStatus()) {
            JOptionPane.showMessageDialog(frame, "Unable to connect to server, please try again in 5 minutes");
        }

    }//end of go()

    public void display() {
        frame.setVisible(true);
    }//end of display()

    private void formWindowClosing(java.awt.event.WindowEvent evt) {
        int optionChoice = JOptionPane.showConfirmDialog(frame, "Are you sure to exit?", "Exit program?", JOptionPane.YES_NO_OPTION);
        if (optionChoice == JOptionPane.YES_OPTION) {
            System.exit(1);
        } else {
        }
        // TODO add your handling code here:
    }

    private class LoginButtonListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            /*

             * LOGIN UI MAIN LISTENER

             */
            if (e.getSource() == loginUI.getLoginButton()) {//login button
                boolean loginStatus = false;
                //validate Password
                loginStatus = system.login(loginUI.getUserName().getText(), loginUI.getPasswordField().getPassword());
                //show home screen
                if (loginStatus == true) {
                    //set user
                    homeUI = new HomeUI();
                    homeUI.getUserPanel().setUser(system.getUser());
                    homeUI.getUserPanel().validate();
                    system.refresh();
                    homeUI.setItemArr(system.getItemArr());
                    homeUI.initiateHomeUI();

                    //add listener to home
                    homeUI.addHomePanelListener(homePanelListener);
                    homeUI.addBidButtonListener(btnBidListener);

                    loginUI.setVisible(false);
                    homeUI.setVisible(true);
                    loginUI.reset();
                    frame.getContentPane().remove(loginUI);
                    frame.getContentPane().add(homeUI);
                    frame.validate();
                    frame.repaint();
                } else { //invalid username and password
                    JOptionPane.showMessageDialog(frame, "Different username and password combination, please try again");
                }//close if
                /*

                 * REGISTER UI

                 */
            } else if (e.getSource() == loginUI.getRegisterButton()) {
                registerUI = new RegisterUI();
                registerUI.initiateRegisterUI();
                registerUI.addRegisterUIListener(registerUIListener);
                loginUI.reset();
                loginUI.setVisible(false);
                registerUI.setVisible(true);
                frame.getContentPane().remove(loginUI);
                frame.getContentPane().add(registerUI);
                frame.validate();
                frame.repaint();

            }//close if
        }//end of actionPerformed()
    }//end of LoginButtonListener

    private class HomePanelListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == homeUI.getPanel().getRefreshButton()) {
                homeUI.setItemArr(null);
                homeUI.refreshScrollPanel();
                boolean refreshStatus = system.refresh();
                if (refreshStatus == true) {
                    JOptionPane.showMessageDialog(frame, "Done!");
                    homeUI.setItemArr(system.getItemArr());
                    homeUI.createItemPanels();
                    homeUI.addBidButtonListener(btnBidListener);
                    homeUI.validate();
                    frame.validate();
                    homeUI.repaint();
                } else {
                    JOptionPane.showMessageDialog(frame, "Error, please refresh");
                    homeUI.validate();
                    frame.validate();
                    homeUI.repaint();
                }

            } else if (e.getSource() == homeUI.getPanel().getSearchButton()) {//search function
                String toSearch = JOptionPane.showInputDialog(frame, "Search for item name: ");
                if (toSearch != null) {
                    system.search(toSearch);
                    homeUI.refreshScrollPanel();
                    homeUI.setItemArr(system.getItemSearched());
                    homeUI.createItemPanels();
                    homeUI.addBidButtonListener(btnBidListener);
                    homeUI.validate();
                    homeUI.repaint();
                }

            } else if (e.getSource() == homeUI.getPanel().getSortButton()) {
                String[] options = {"Name", "Starting Bid", "Finish Date"};
                int n = JOptionPane.showOptionDialog(frame, "Sort items by: ", "Sort", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
                system.sort(n);
                homeUI.refreshScrollPanel();
                homeUI.createItemPanels();
                homeUI.addBidButtonListener(btnBidListener);
                homeUI.validate();
                homeUI.repaint();
            } else if (e.getSource() == homeUI.getPanel().getPlaceObjectButton()) {// place item
                itemUI = new PlaceItemUI();
                itemUI.initiatePlaceItemUI();
                itemUI.addListeners(placeItemUIListener);
                homeUI.setVisible(false);
                itemUI.setVisible(true);
                frame.getContentPane().remove(homeUI);
                frame.getContentPane().add(itemUI);
                frame.validate();
                frame.repaint();
            } else if (e.getSource() == homeUI.getPanel().getRechargeTokenButton()) { //Recharge
                rechargeUI = new RechargeTokenUI();
                rechargeUI.initiateRechargeUI();
                rechargeUI.addListeners(rechargeUIListener);
                homeUI.setVisible(false);
                rechargeUI.setVisible(true);
                frame.getContentPane().remove(homeUI);
                frame.getContentPane().add(rechargeUI);
                frame.validate();
                frame.repaint();
            } else if (e.getSource() == homeUI.getPanel().getViewHistoryButton()) {
                try {
                    system.viewHistory();
                } catch (IOException ex) {
                    Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null, ex);
                }

            } else if (e.getSource() == homeUI.getPanel().getLogoutButton()) {
                int optionChoice = JOptionPane.showConfirmDialog(frame, "Are you sure you want to logout?", "Logout Online Auction Game", JOptionPane.YES_NO_OPTION);
                if (optionChoice == JOptionPane.YES_OPTION) {
                    system.logout();
                    homeUI.setVisible(false);
                    loginUI.setVisible(true);
                    frame.getContentPane().remove(homeUI);
                    homeUI = new HomeUI();
                    frame.getContentPane().add(loginUI);
                    frame.validate();
                    frame.repaint();
                }
            }
        }
    }//end of HomePanelListener

    private class PlaceItemListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == itemUI.getBtnSubmit()) {
                boolean placeStatus = false;
                Calendar currentDate = Calendar.getInstance();
                Calendar limitDate = Calendar.getInstance();
                limitDate.add(Calendar.YEAR, 1);
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
                String expression = "^(18|19|20|21)\\d{2}[- / ]?(0[1-9]|1[012]|[1-9])[- /]?(0[1-9]|[1-9]|[12][0-9]|3[01])$";
                try {
                    Integer.parseInt(itemUI.getTxtStartBid().getText());
                    if (itemUI.getTxtItemName().getText().isEmpty()) {
                        JOptionPane.showMessageDialog(frame, "Please enter name of the item");
                    } else if (formatter.parse(itemUI.getTxtFinishDate().getText()).before(currentDate.getTime())) {
                        JOptionPane.showMessageDialog(frame, "Finish Date should be later than current date");
                    } else if (formatter.parse(itemUI.getTxtFinishDate().getText()).after(limitDate.getTime())) {
                        JOptionPane.showMessageDialog(frame, "Item should not be more than 1 year long");
                    } else if (Integer.parseInt(itemUI.getTxtStartBid().getText()) <= 0) {
                        JOptionPane.showMessageDialog(frame, "Starting Bid should not be 0 or less");
                    } else if (!Pattern.matches(expression, itemUI.getTxtFinishDate().getText())) {
                        JOptionPane.showMessageDialog(frame, "Date must be in YYYY/MM/DD format");
                    } else {
                        try {
                            placeStatus = system.placeItem(itemUI.getTxtItemName().getText(), itemUI.getTxtDescription().getText(), itemUI.getTxtFinishDate().getText(), Integer.parseInt(itemUI.getTxtStartBid().getText()));
                        } catch (IOException ex) {
                            Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null, ex);
                        }
                        if (placeStatus == true) {
                            JOptionPane.showMessageDialog(frame, "Success placing new item!");
                            itemUI.setVisible(false);
                            homeUI.setVisible(true);
                            frame.getContentPane().remove(itemUI);
                            frame.getContentPane().add(homeUI);
                            frame.validate();
                            frame.repaint();
                        } else {
                            JOptionPane.showMessageDialog(frame, "Sorry, error occured");
                        }//close if
                    }
                } catch (ParseException ex) {
                    Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null, ex);
                    JOptionPane.showMessageDialog(frame, "Uncompatible date type, please enter in YYYY/MM/DD format");
                } catch (NumberFormatException ex) {
                    JOptionPane.showMessageDialog(frame, "Invalid starting bid");
                }



            } else if (e.getSource() == itemUI.getBtnCancel()) {
                int optionChoice = JOptionPane.showConfirmDialog(frame, "Are you sure you want to cancel?", "Cancel Register?", JOptionPane.YES_NO_OPTION);
                if (optionChoice == JOptionPane.YES_OPTION) {
                    //show login panel
                    itemUI.setVisible(false);
                    homeUI.setVisible(true);
                    frame.getContentPane().remove(itemUI);
                    frame.getContentPane().add(homeUI);
                    frame.validate();
                    frame.repaint();
                }//close if
            }
        }
    }

    private class RechargeListener implements ActionListener {

        private static final int MAX_RECHARGE = 500;

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == rechargeUI.getBtnSubmit()) {
                boolean rechargeStatus = false;
                int rechargeAmt = Integer.parseInt(rechargeUI.getRechargeAmt().getText());
                if (rechargeAmt <= 0) {
                    JOptionPane.showMessageDialog(frame, "Recharge amount must not be 0 or less!");
                } else if (rechargeAmt > MAX_RECHARGE) {
                    JOptionPane.showMessageDialog(frame, "Maximum recharge amount is 500");
                } else {
                    try {
                        rechargeStatus = system.rechargeToken(rechargeAmt);
                    } catch (IOException ex) {
                        Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }

                if (rechargeStatus == true) {
                    JOptionPane.showMessageDialog(frame, "Success recharging token");
                    system.getUser().incrementToken(rechargeAmt);
                    homeUI.getUserPanel().refreshUserPanel();
                    homeUI.getUserPanel().validate();
                    rechargeUI.setVisible(false);
                    homeUI.setVisible(true);
                    frame.getContentPane().remove(rechargeUI);
                    frame.getContentPane().add(homeUI);
                    frame.validate();
                    frame.repaint();
                } else {
                    JOptionPane.showMessageDialog(frame, "Sorry, error occured");
                }//close if

            } else if (e.getSource() == rechargeUI.getBtnCancel()) {
                int optionChoice = JOptionPane.showConfirmDialog(frame, "Are you sure you want to cancel?", "Cancel Register?", JOptionPane.YES_NO_OPTION);
                if (optionChoice == JOptionPane.YES_OPTION) {
                    //show login panel
                    rechargeUI.setVisible(false);
                    homeUI.setVisible(true);
                    frame.getContentPane().remove(rechargeUI);
                    frame.getContentPane().add(homeUI);
                    frame.validate();
                    frame.repaint();
                }
            }

        }
    }

    private class BidButtonListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            boolean bidStatus = false;
            Item itemBeingBid = ((ItemPanel) ((JButton) e.getSource()).getParent()).getItem();
            String bidValue = JOptionPane.showInputDialog(frame, "Please enter the value you wish to bid for -" + itemBeingBid.getItemName() + "-, item ID: " + itemBeingBid.getItemId(), "Confirm bid", JOptionPane.OK_CANCEL_OPTION);
            if (bidValue != null) {
                int bid = Integer.parseInt(bidValue);

                if (system.getUser().getUserID() == ((ItemPanel) ((JButton) e.getSource()).getParent()).getItem().getSellerID()) {
                    JOptionPane.showMessageDialog(frame, "Sorry, you cannot bid on your own item!");
                } else {
                    if (bid < itemBeingBid.getStartingBid()) {
                        JOptionPane.showMessageDialog(frame, "You must bid above the starting bid");
                    } else if (bid <= system.getUser().getToken()) {
                        try {
                            bidStatus = system.bid(bid, itemBeingBid.getItemId());
                        } catch (IOException ex) {
                            Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    } else {
                        JOptionPane.showMessageDialog(frame, "Sorry, you do not have enough token!");
                    }
                }
            }

            if (bidStatus == true) {
                system.getUser().decrementToken(Integer.parseInt(bidValue));
                homeUI.getUserPanel().refreshUserPanel();
                homeUI.getUserPanel().validate();
                JOptionPane.showMessageDialog(frame, "Success bidding for item id: " + itemBeingBid.getItemId() + ", Please refresh to see changes");
            } else if (bidStatus == false && bidValue != null) {
                JOptionPane.showMessageDialog(frame, "Error occured, please try again later");
            }
        }
    }//end of BidButtonListener

    private class RegisterButtonListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            /*

             * REGISTER UI SUBMIT BUTTON

             */
            if (e.getSource() == registerUI.getSubmitButton()) {
                boolean regStatus = false;
                String dateExpression = "^(18|19|20|21)\\d{2}[- / ]?(0[1-9]|1[012]|[1-9])[- /]?(0[1-9]|[1-9]|[12][0-9]|3[01])$";
                String mailExpression = "^[\\w\\-]([\\.\\w])+[\\w]+@([\\w\\-]+\\.)+[A-Z]{2,4}$";

                //validation
                if (registerUI.getUsername().getText().isEmpty() || registerUI.getUsername().getText().length() <= 4) {
                    JOptionPane.showMessageDialog(frame, "Sorry, username must not be empty and should be more than 4 characters long");
                } else if (registerUI.getPassword1().getPassword().length <= 4 || registerUI.getPassword2().getPassword().length <= 4) {
                    JOptionPane.showMessageDialog(frame, "Sorry, password must not be empty and must be more than 4 characters long");
                } else if (!Arrays.equals(registerUI.getPassword1().getPassword(), registerUI.getPassword2().getPassword())) {
                    JOptionPane.showMessageDialog(frame, "Sorry, password must match");
                } else if (registerUI.getFirstName().getText().isEmpty()) {
                    JOptionPane.showMessageDialog(frame, "Sorry, first name must not be empty");
                } else if (registerUI.getLastName().getText().isEmpty()) {
                    JOptionPane.showMessageDialog(frame, "Sorry, last name must not be empty");
                } else if (!Pattern.matches(dateExpression, registerUI.getDofBirth().getText())) {
                    JOptionPane.showMessageDialog(frame, "Sorry, Finish Date must be in yyyy/mm/dd format");
                } else if (registerUI.getDofBirth().getText().isEmpty()) {
                    JOptionPane.showMessageDialog(frame, "Sorry, date of birth should not be empty and in dd/mm/yyyy format");
                } else if (registerUI.getAddress().getText().isEmpty()) {
                    JOptionPane.showMessageDialog(frame, "Sorry, address must not be empty");
                } else if (registerUI.geteMail().getText().isEmpty()) {
                    JOptionPane.showMessageDialog(frame, "Sorry, e-mail address must not be empty");
                } else if (Pattern.matches(mailExpression, registerUI.geteMail().getText())) {
                    JOptionPane.showMessageDialog(frame, "Invalid email address");
                } else {
                    String username = registerUI.getUsername().getText();
                    String password = String.valueOf(registerUI.getPassword1().getPassword());
                    String fName = registerUI.getFirstName().getText();
                    String lName = registerUI.getLastName().getText();
                    String dob = registerUI.getDofBirth().getText();
                    String address = registerUI.getAddress().getText();
                    String eMail = registerUI.geteMail().getText();

                    //send data to server
                    try {
                        regStatus = system.register(username, password, fName, lName, dob, address, eMail);
                    } catch (IOException ex) {
                        Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(MainUI.class.getName()).log(Level.SEVERE, null, ex);
                    }//close try-catch
                    if (regStatus == true) {
                        JOptionPane.showMessageDialog(frame, "Succes registering!");
                        registerUI.setVisible(false);
                        loginUI.setVisible(true);
                        frame.getContentPane().remove(registerUI);
                        frame.getContentPane().add(loginUI);
                        frame.validate();
                        frame.repaint();
                    } else {
                        JOptionPane.showMessageDialog(frame, "Sorry, error occured");
                    }
                }//close if



                /*

                 * REGISTER UI CANCEL BUTTON

                 */
            } else if (e.getSource() == registerUI.getCancelButton()) {
                int optionChoice = JOptionPane.showConfirmDialog(frame, "Are you sure you want to cancel?", "Cancel Register?", JOptionPane.YES_NO_OPTION);
                if (optionChoice == JOptionPane.YES_OPTION) {
                    //show login panel
                    registerUI.setVisible(false);
                    loginUI.setVisible(true);
                    frame.getContentPane().remove(registerUI);
                    frame.getContentPane().add(loginUI);
                    frame.validate();
                    frame.repaint();
                }//close if
            }//close if
        }//end of actionPerformed
    }//end of RegisterButtonListener
}
